﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using eLuk.CommandEngine;
using eLuk.Entity;
using System.IO;
using System.Runtime.Serialization;
using Windows.Storage;
using Windows.Storage.Streams;
using eLuk.Security;

namespace eLuk.Runtime
{
	public class IMAPSession
	{
		public event IMAPObjectUpdated IMAPObjectUpdated;

		private eLuk.Security.Encryption Encryption { get; set; }
		private eLuk.Security.Decryption Decryption { get; set; }
		private eLuk.Security.DataProtection DataProtection { get; set; }
		public IMAPState CurrentState { get; set; }
		public MessageParserTokens MessageParserTokens { get; set; }
		public IMAPCommandEngine Engine { get; set; }
		internal EmailServer Server { get; set; }
		public IMAPSession( EmailServer _server )
		{
			this.Server = _server;
			this.CurrentState = new IMAPInitialState();
			//this.IMAPFolder = new IMAPFolder();
			this.Encryption = new Encryption();
			this.Decryption = new Decryption();
			this.DataProtection = new DataProtection();
			this.MessageParserTokens = new MessageParserTokens();
		}
		public async Task SyncMailClient()
		{
			IMAPObjectUpdatedEventArgs eiou = null;

			eLukFolder _folder = null;
			if (this.CurrentState == null)
			{
				this.CurrentState = new IMAPInitialState();
				if ( this.IMAPObjectUpdated != null )
				{
					eiou = new IMAPObjectUpdatedEventArgs();
					eiou.Message = "Session initialized";
					eiou.OperationOption = OperationOption.StatusUpdate;
					this.IMAPObjectUpdated( this, eiou );
				}
			}

			if ( this.CurrentState is IMAPInitialState )
			{
				IMAPInitialState initState = this.CurrentState as IMAPInitialState;
				if ( this.IMAPObjectUpdated != null )
				{
					eiou = new IMAPObjectUpdatedEventArgs();
					eiou.Message = "Connecting to the server";
					eiou.OperationOption = OperationOption.StatusUpdate;
					this.IMAPObjectUpdated( this, eiou );
				}
				await initState.Connect( this );
			}
			
			if ( this.CurrentState is IMAPConnectedState )
			{
				IMAPConnectedState connectedState = this.CurrentState as IMAPConnectedState;
				if ( this.IMAPObjectUpdated != null )
				{
					eiou = new IMAPObjectUpdatedEventArgs();
					eiou.Message = "Authenticating the user credentials";
					eiou.OperationOption = OperationOption.StatusUpdate;
					this.IMAPObjectUpdated( this, eiou );
				}
				await connectedState.Login( this );
			}
			
			if ( this.CurrentState is IMAPAuthenticatedState )
			{
				IMAPAuthenticatedState authenticatedState = this.CurrentState as IMAPAuthenticatedState;
				this.CurrentState = new IMAPBrowserState();
			}
			else if ( this.CurrentState is IMAPAuthenticationFailedState )
			{
				this.CurrentState = new IMAPInitialState();
				if ( this.IMAPObjectUpdated != null )
				{
					eiou = new IMAPObjectUpdatedEventArgs();
					eiou.Message = "Authentication Failed. Invalid Credentials";
					eiou.OperationOption = OperationOption.AuthenticationFailed;
					this.IMAPObjectUpdated( this, eiou );
				}
				return;
			}

			if ( this.CurrentState is IMAPBrowserState )
			{
				IMAPBrowserState browserState = this.CurrentState as IMAPBrowserState;
				if ( this.IMAPObjectUpdated != null )
				{
					eiou = new IMAPObjectUpdatedEventArgs();
					eiou.Message = "Browsing the email account";
					eiou.OperationOption = OperationOption.StatusUpdate;
					this.IMAPObjectUpdated( this, eiou );
				}
				_folder = await browserState.List( this );
				//await browserState.FetchEnvelope( this, new MailMessage() );
				if ( this.IMAPObjectUpdated != null )
				{
					eiou = new IMAPObjectUpdatedEventArgs();
					eiou.IMAPObject = _folder;
					eiou.OperationOption = OperationOption.CompareFolders;
					this.IMAPObjectUpdated( this, eiou );
				}

				await browserState.Examine( this, _folder );

				if ( this.IMAPObjectUpdated != null )
				{
					eiou = new IMAPObjectUpdatedEventArgs();
					eiou.IMAPObject = _folder;
					eiou.OperationOption = OperationOption.CompareFolders;
					this.IMAPObjectUpdated( this, eiou );
				}

				if ( this.IMAPObjectUpdated != null )
				{
					eiou = new IMAPObjectUpdatedEventArgs();
					eiou.Message = "Retreiving messages. This may take some time, sit back and relax.";
					eiou.OperationOption = OperationOption.StatusUpdate;
					this.IMAPObjectUpdated( this, eiou );
				}

				await browserState.Select( this, _folder, true );

				if ( this.IMAPObjectUpdated != null )
				{
					eiou = new IMAPObjectUpdatedEventArgs();
					eiou.Message = "Saving the messages and preparing the account.";
					eiou.OperationOption = OperationOption.StatusUpdate;
					this.IMAPObjectUpdated( this, eiou );
				}

				if ( this.IMAPObjectUpdated != null )
				{
					eiou = new IMAPObjectUpdatedEventArgs();
					eiou.IMAPObject = _folder;
					eiou.OperationOption = OperationOption.WriteToDisk;
					this.IMAPObjectUpdated( this, eiou );
				}

				if ( this.IMAPObjectUpdated != null )
				{
					eiou = new IMAPObjectUpdatedEventArgs();
					eiou.IMAPObject = _folder;
					eiou.OperationOption = OperationOption.Ready;
					this.IMAPObjectUpdated( this, eiou );
				}
				

			}

		}

	}
}
